<template>
    <table v-if="property.type === 'table'" class="vo-drag-item-table" :class="{'active': isLayoutActive('table')}" border="0" cellpadding="0" cellspacing="0" @click.stop.prevent="handleClick">
        <template v-for="(tr, tri) in properties">
            <VoDragLayoutFormItem
                :key="tri"
                :model="model"
                :property="tr"
                :select-property="selectProperty"
                :parent="tr.properties"
                :layout="property"
                @item-select="itemSelect"
                @item-delete="itemDelete"
                @item-copy="itemCopy"
            ></VoDragLayoutFormItem>
        </template>
        <tr>
            <VoDragLayoutFormItemMask
                :property="property"
                :selectProperty="selectProperty"
                @on-delete="handleDelete"
                @on-copy="handleCopy"
                @on-row-add="handleRowAdd"
                @on-table-row-add="tableRowAdd"
                @on-table-column-add="tableColumnAdd"
            ></VoDragLayoutFormItemMask>
        </tr>
    </table>
    <tr v-else-if="property.type === 'tr'" class="vo-drag-item-tr">
        <template v-for="(td, tdi) in properties">
            <td v-if="td.attrs.colspan && td.attrs.rowspan"
                class="vo-drag-item-td"
                :class="{'active': isLayoutActive('td', td)}"
                @click.stop.prevent="handleTdClick(td)"
                :key="tdi"
                v-bind="td.attrs"
            >
                <VoDragLayoutFormItem
                    :model="model"
                    :property="td"
                    :select-property="selectProperty"
                    :parent="td.properties"
                    @item-select="itemSelect"
                    @item-delete="itemDelete"
                    @item-copy="itemCopy"
                ></VoDragLayoutFormItem>
                <VoDragLayoutFormItemMask
                    :property="td"
                    :selectProperty="selectProperty"
                    :parent="property"
                    :layout="layout"
                    @on-delete="handleDelete"
                    @on-copy="handleCopy"
                    @on-row-add="handleRowAdd"
                    @on-table-row-add="tableRowAdd"
                    @on-table-column-add="tableColumnAdd"
                    @on-table-td-set="tableTdSet"
                ></VoDragLayoutFormItemMask>
            </td>
        </template>
    </tr>
    <el-row v-else-if="property.type === 'row'" v-bind="property.props" class="vo-drag-item-row" :class="{'active': isLayoutActive('row')}">
        <el-col v-for="(col, coli) in properties" v-bind="col.props" :key="coli" class="vo-drag-item-col">
            <VoDragLayoutFormItem
                :model="model"
                :property="col"
                :select-property="selectProperty"
                :parent="properties"
                :layout="property"
                @item-select="itemSelect"
                @item-delete="itemDelete"
                @item-copy="itemCopy"
            ></VoDragLayoutFormItem>
        </el-col>
        <VoDragLayoutFormItemMask
            :property="property"
            :selectProperty="selectProperty"
            @on-delete="handleDelete"
            @on-copy="handleCopy"
            @on-row-add="handleRowAdd"
            @on-table-row-add="tableRowAdd"
            @on-table-column-add="tableColumnAdd"
        ></VoDragLayoutFormItemMask>
    </el-row>
    <el-tabs v-else-if="property.type === 'tabs'" v-model="property.defaultValue" class="vo-drag-item-tabs" :class="{'active': isLayoutActive('tabs')}" @tab-click.native.stop.prevent>
        <el-tab-pane v-for="(pane, panei) in properties" v-bind="pane.props" :key="panei">
            <VoDragLayoutFormItem
                :model="model"
                :property="pane"
                :select-property="selectProperty"
                :parent="properties"
                :layout="property"
                @item-select="itemSelect"
                @item-delete="itemDelete"
                @item-copy="itemCopy"
            ></VoDragLayoutFormItem>
        </el-tab-pane>
        <VoDragLayoutFormItemMask
            :property="property"
            :selectProperty="selectProperty"
            @on-delete="handleDelete"
            @on-copy="handleCopy"
            @on-row-add="handleRowAdd"
            @on-table-row-add="tableRowAdd"
            @on-table-column-add="tableColumnAdd"
        ></VoDragLayoutFormItemMask>
    </el-tabs>
    <div v-else class="vo-drag-view">
        <vueDraggable
            v-if="!property.widget"
            class="form-draggable"
            data-dragto="form"
            v-model="property.properties"
            v-bind="formDragOptions"
        >
            <template v-for="(item, index) in properties">
                <VoDragLayoutFormItem
                    :key="index"
                    :model="model"
                    :property="item"
                    :select-property="selectProperty"
                    :parent="properties"
                    @item-select="itemSelect"
                    @item-delete="itemDelete"
                    @item-copy="itemCopy"
                ></VoDragLayoutFormItem>
            </template>
        </vueDraggable>
        <div v-else class="vo-drag-view-widget" :class="{'active': isActive}" @click.stop.prevent="handleClick">
            <VoSchemaFormItem :model="model" :property="property"></VoSchemaFormItem>
            <VoDragLayoutFormItemMask
                :property="property"
                :selectProperty="selectProperty"
                @on-delete="handleDelete"
                @on-copy="handleCopy"
                @on-row-add="handleRowAdd"
                @on-table-row-add="tableRowAdd"
                @on-table-column-add="tableColumnAdd"
            ></VoDragLayoutFormItemMask>
        </div>
    </div>
</template>

<script>
import VueDraggable from 'vuedraggable'
import VoSchemaFormItem from '@/packages/SchemaForm/FormItem.vue'
import VoDragLayoutFormItemMask from './DragLayoutItemMask.vue'
import { clone } from '@/utils/clone'

export default {
    name: 'VoDragLayoutFormItem',
    components: {
        VueDraggable,
        VoSchemaFormItem,
        VoDragLayoutFormItemMask
    },
    props: {
        model: Object,
        selectProperty: Object,
        property: Object,
        parent: Array,
        layout: Object
    },
    data() {
        return {
            formDragOptions: {
                handle: '.drag-bar',
                chosenClass: 'form-chosen',
                animation: 200,
                group: 'draggroup',
                tag: 'el-row'
            }
        }
    },
    computed: {
        isActive() {
            const { selectProperty, property } = this
            if (selectProperty && property) {
                return selectProperty === property
            }
            return false
        },
        properties() {
            return this.property ? (this.property.properties || []) : []
        }
    },
    methods: {
        isLayoutActive(type, p) {
            const property = p || this.property
            const { selectProperty } = this
            if (!selectProperty || !property) return false;
            return selectProperty === property && selectProperty.type === type && property.type === type
        },
        handleClick(e) {
            this.$emit('item-select', this.property)
        },
        handleDelete() {
            if (this.parent) {
                const index = this.parent.findIndex(e => e.model === this.property.model)
                this.parent.splice(index, 1)
            }
            this.$nextTick(() => {
                this.$emit('item-delete', this.property)
            })
        },
        handleCopyProperty(data) {
            if (data.widget) {
                console.log(data.model);
                data.model = `${data.widget}_${Math.floor(Math.random() * 1000000)}`
            }
            if (data.properties) {
                data.properties.forEach(e => {
                    this.handleCopyProperty(e)
                })
            }
            return data
        },
        handleCopy() {
            const index = this.parent.findIndex(e => e === this.property)
            this.parent.splice(index + 1, 0, this.handleCopyProperty(clone(this.property)))
            this.$emit('item-copy', this.property)
        },
        handleRowAdd() {
            this.$emit('item-row-add', this.property)
        },
        itemSelect(p) {
            this.$emit('item-select', p)
        },
        itemDelete(p) {
            this.$emit('item-delete', p)
        },
        itemCopy(p) {
            this.$emit('item-copy', p)
        },
        handleTdClick(p) {
            this.$emit('item-select', p)
        },
        // table
        // 添加行
        tableRowAdd() {
            const { property } = this;
            if (!property.properties) {
                this.$set(property, 'properties', [])
            }
            let len = 1;
            if (property.properties[0] && property.properties[0].properties) {
                const tdLen = property.properties[0].properties.reduce((t, e) => {
                    t += e.attrs ? (e.attrs.colspan || 1) : 1
                    return t
                }, 0)
                len = Math.max(len, tdLen)
            }
            property.properties.push({
                type: 'tr',
                props: {},
                properties: Array(len).fill('').map(e => ({
                    type: 'td',
                    props: {},
                    attrs: {
                        colspan: 1,
                        rowspan: 1
                    },
                    properties: []
                }))
            })
        },
        // 添加列
        tableColumnAdd() {
            const { property } = this;
            if (!property.properties) {
                this.$set(property, 'properties', [])
            }
            property.properties.forEach(tr => {
                if (tr.properties) {
                    tr.properties.push({
                        type: 'td',
                        props: {},
                        attrs: {
                            colspan: 1,
                            rowspan: 1
                        },
                        properties: []
                    })
                }
            })
        },
        // td设置
        tableTdSet(el) {
            const { key } = el
            switch (key) {
                case 'push-left':
                    this.tdPushLeft(el)
                    break;
                case 'push-right':
                    this.tdPushRight(el)
                    break;
                case 'push-top':
                    this.tdPushTop(el)
                    break;
                case 'push-bottom':
                    this.tdPushBottom(el)
                    break;
                case 'merge-right':
                    this.tdMergeRight(el)
                    break;
                case 'merge-bottom':
                    this.tdMergeBottom(el)
                    break;
                case 'split-column':
                    this.tdSplitColumn(el)
                    break;
                case 'split-row':
                    this.tdSplitRow(el)
                    break;
                case 'delete-column':
                    this.tdDeleteColumn(el)
                    break;
                case 'delete-row':
                    this.tdDeleteRow(el)
                    break;
                default:
                    break;
            }
        },
        // 向左插入列
        tdPushLeft(el) {
            this.$message.warning('还没做哦')
        },
        // 向右插入列
        tdPushRight(el) {
            this.$message.warning('还没做哦')
        },
        // 向上插入行
        tdPushTop(el) {
            this.$message.warning('还没做哦')
        },
        // 向下插入行
        tdPushBottom(el) {
            this.$message.warning('还没做哦')
        },
        // 向右合并
        tdMergeRight(el) {
            const { property } = el
            const realProperties = this.property.properties.filter(e => e.attrs.colspan)
            console.log(realProperties);
            const index = realProperties.findIndex(e => e === property)
            if (index >= realProperties.length - 1) return;
            // 当前 td 的右边的 td
            const rightTd = realProperties[index + 1]
            property.attrs.colspan += rightTd.attrs.colspan
            rightTd.attrs.colspan = 0
            property.properties = [
                ...property.properties,
                ...rightTd.properties
            ]
            rightTd.properties = []
        },
        // 向下合并
        tdMergeBottom(el) {
            const { layout } = this;
            if (!layout && !layout.type !== 'table') return;
            const trIndex = layout.properties.findIndex(e => e === this.property)
            if (trIndex >= layout.properties.length - 1) return;
            const { property } = el
            const tdIndex = this.property.properties.findIndex(e => e === property)
            const tdRowspan = property.attrs.rowspan
            const nextTr = layout.properties[trIndex + tdRowspan]
            const nextTd = nextTr.properties.find((e, i) => tdIndex === i)
            if (nextTd) {
                const nextTdRowspan = nextTd.attrs.rowspan
                property.attrs.rowspan += nextTdRowspan
                nextTd.attrs.rowspan = 0
                property.properties = [
                    ...property.properties,
                    ...nextTd.properties
                ]
                nextTd.properties = []
            }
        },
        // 拆分成列
        tdSplitColumn(el) {
            const { property } = el
            const min = this.property.properties.findIndex(e => e === property)
            const max = property.attrs.colspan + min;
            this.property.properties.forEach((e, i) => {
                if (e === property) {
                    e.attrs.colspan = 1
                }
                if (i > min && i < max) {
                    e.attrs.colspan = 1
                }
            })
        },
        // 拆分成行
        tdSplitRow(el) {
            const { property } = el
            // tdindex
            const tdIndex = this.property.properties.findIndex(e => e === property)
            // trindex
            const min = this.layout.properties.findIndex(e => e === this.property)
            const max = property.attrs.rowspan + min;
            this.layout.properties.forEach((e, i) => {
                if (e === this.property) {
                    if (e.properties[tdIndex]) {
                        e.properties[tdIndex].attrs.rowspan = 1
                    }
                }
                if (i > min && i < max) {
                    if (e.properties[tdIndex]) {
                        e.properties[tdIndex].attrs.rowspan = 1
                    }
                }
            })
        },
        // 删除列
        tdDeleteColumn(el) {
            const { property } = el;
            const tdIndex = this.property.properties.findIndex(e => e === property)
            this.layout.properties.forEach((tr) => {
                const tdList = tr.properties.splice(tdIndex, 1)
                const td = tdList.length ? tdList[0] : null
                if (td && td.attrs.colspan > 1 && tr.properties[tdIndex]) {
                    tr.properties[tdIndex].attrs.colspan = td.attrs.colspan - 1
                    tr.properties[tdIndex].properties = [
                        ...tr.properties[tdIndex].properties,
                        ...td.properties
                    ]
                }
                let mergetColspan = 1;
                for (let index = tr.properties.length - 1; index >= 0; index--) {
                    const td = tr.properties[index];
                    if (td.attrs.colspan === 0) {
                        mergetColspan += 1
                    } else {
                        td.attrs.colspan = mergetColspan
                        mergetColspan = 1
                    }
                }
            })
        },
        // 删除行
        tdDeleteRow(el) {
            const trIndex = this.layout.properties.findIndex(e => e === this.property)

            const trList = this.layout.properties.splice(trIndex, 1)
            const tr = trList.length ? trList[0] : null
            tr.properties.forEach((td, tdIndex) => {
                if (td.attrs.rowspan > 1) {
                    const nextTr = this.layout.properties[trIndex]
                    if (nextTr) {
                        const nextTd = nextTr.properties[tdIndex]
                        if (nextTd) {
                            nextTd.attrs.rowspan = td.attrs.rowspan - 1;
                            nextTd.properties = [
                                ...nextTd.properties,
                                ...td.properties
                            ]
                        }
                    }
                }
            })

            const mergetColspan = [];
            for (let index = this.layout.properties.length - 1; index >= 0; index--) {
                const tr = this.layout.properties[index];
                tr.properties.forEach((td, i) => {
                    if (td.attrs.rowspan === 0) {
                        mergetColspan[i] = (mergetColspan[i] || 1) + 1
                    } else {
                        td.attrs.rowspan = mergetColspan[i] || 1
                        mergetColspan[i] = 1
                    }
                })
            }
        }
    }
}
</script>

<style lang="scss" scoped>
$color-blue: #0094ff;
$color-yellow: #E6A23C;
$color-border-one: #DCDFE6;

.vo-drag-view{
    position: relative;
    .vo-drag-view-widget{
        border: 2px dashed #E4E7ED;
        box-sizing: border-box;
        padding: 5px;
        overflow: hidden;
        &:hover{
            border-color: $color-blue;
        }
        &.active{
            border-style: solid;
            border-color: $color-blue;
        }
    }
}
.form-draggable{
    min-height: 60px;
}
.vo-drag-item-table{
    table-layout: fixed;
    border: 2px solid $color-border-one;
    width: 100%;
    padding: 5px;
    background: #FDFAF5;
    position: relative;
    min-height: 60px;
    &:hover{
        border-color: $color-yellow;
        background: #FDF6EC;
    }
    &.active{
        border-style: solid;
        border-color: $color-yellow;
    }
    .vo-drag-item-tr{
        position: relative;
    }
    .vo-drag-item-td{
        position: relative;
        border: 2px solid $color-border-one;
        padding: 5px;
        &:hover{
            border-color: $color-yellow;
            background: #FDF6EC;
        }
        &.active{
            border-style: solid;
            border-color: $color-yellow;
        }
    }
}
.vo-drag-item-row{
    width: 100%;
    border: 2px solid $color-border-one;
    padding: 5px;
    &:hover{
        border-color: $color-yellow;
    }
    &.active{
        border-style: solid;
        border-color: $color-yellow;
    }
}
.vo-drag-item-tabs{
    border: 2px solid $color-border-one;
    &:hover{
        border-color: $color-yellow;
    }
    &.active{
        border-style: solid;
        border-color: $color-yellow;
    }
}
</style>
